package com.qsw.paper.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qsw.paper.constant.JwtClaimsConstant;
import com.qsw.paper.constant.MessageConstants;
import com.qsw.paper.constant.StatusConstants;
import com.qsw.paper.exception.ObjectException;
import com.qsw.paper.mapper.UsersMapper;
import com.qsw.paper.pojo.dto.AdvisorsDto;
import com.qsw.paper.pojo.dto.AdvisorsQueryDto;
import com.qsw.paper.pojo.entity.Advisors;
import com.qsw.paper.mapper.AdvisorsMapper;
import com.qsw.paper.pojo.entity.Users;
import com.qsw.paper.pojo.vo.AdvisorsListVO;
import com.qsw.paper.pojo.vo.AdvisorsVO;
import com.qsw.paper.result.PageResult;
import com.qsw.paper.service.IAdvisorsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qsw.paper.utils.ThreadLocalUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author qsw
 * @since 2024-11-15
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AdvisorsServiceImpl extends ServiceImpl<AdvisorsMapper, Advisors> implements IAdvisorsService {

    private final UsersMapper usersMapper;

    /**
     * 分页查询导师信息
     *
     * @param queryDto 包含查询条件（导师姓名和职称）以及分页参数的 DTO 对象
     * @return 分页结果，包含总记录数和当前页的导师列表
     */
    @Override
    public PageResult<?> pageList(@NotNull AdvisorsQueryDto queryDto) {
        Page<AdvisorsListVO> advisorsPage = baseMapper.list(new Page<>(queryDto.getPageNum(), queryDto.getPageSize()), queryDto);
        // 返回分页结果，总记录数和导师列表
        return new PageResult<>(advisorsPage.getTotal(), advisorsPage.getRecords());
    }

    /**
     * 添加导师
     *
     * @param advisorsDto dto 包含导师信息的数据传输对象
     */
    @Transactional // 开始事务，确保方法中的所有操作要么全部成功，要么全部回滚
    @Override
    public void save(@NotNull AdvisorsDto advisorsDto) {
        // 获取 DTO 中的邮箱和手机号 图像URL
        String email = advisorsDto.getEmail();
        String phone = advisorsDto.getPhone();
        String avatar = advisorsDto.getAvatar();
        // 1. 先向用户表插入数据
        Users user = Users.builder().role(StatusConstants.TWO) // 设置角色为导师
                .createdAt(LocalDateTime.now()) // 设置创建时间为当前时间
                .username(advisorsDto.getUsername()) // 设置用户名为传入的用户名（通常是工号）
                .status(StatusConstants.ONE) // 设置状态为启用状态，假设 StatusConstants.ONE 表示启用
                .password(DigestUtils.md5DigestAsHex(JwtClaimsConstant.INITIAL_PASSWORD.getBytes())) // 设置初始密码（经过 MD5 加密）
                .email(!StringUtils.isBlank(email) ? email : null) // 如果邮箱不为空，则设置邮箱，否则设置为 null
                .phone(!StringUtils.isBlank(phone) ? phone : null) // 如果手机号不为空，则设置手机号，否则设置为 null
                .avatar(!StringUtils.isBlank(avatar) ? avatar : null).build(); // 构建 Users 对象
        // 插入用户表
        usersMapper.insert(user);
        // 2. 创建导师表的数据
        Advisors advisor = Advisors.builder().collegeId(advisorsDto.getCollegeId()) // 设置学院 ID，来自传入的 DTO
                .createdAt(LocalDateTime.now()) // 设置创建时间为当前时间
                .name(advisorsDto.getName()) // 设置导师姓名
                .title(advisorsDto.getTitle()) // 设置职称
                .userId(user.getUserId()) // 设置关联的用户 ID，使用刚插入用户表后回填的主键
                .build(); // 构建 Advisors 对象
        // 插入导师表
        baseMapper.insert(advisor);
    }

    /**
     * 修改导师信息
     *
     * @param advisorsDto dto
     * @param id          导师id
     */
    @Transactional
    @Override
    public void update(@NotNull AdvisorsDto advisorsDto, Integer id) {

        Integer userId = advisorsDto.getUserId();

        // 查询当前用户数据
        Users currentUser = usersMapper.selectById(userId);
        if (currentUser == null) {
            throw new ObjectException("用户不存在");
        }

        // 获取前端传递的数据并去除空格
        String newEmail = StringUtils.trimToNull(advisorsDto.getEmail());
        String newPhone = StringUtils.trimToNull(advisorsDto.getPhone());
        String newAvatar = StringUtils.trimToNull(advisorsDto.getAvatar());

        // 创建动态更新语句
        LambdaUpdateWrapper<Users> updateWrapper = new LambdaUpdateWrapper<>();
        boolean needUpdate = false;

        // 检查新值与当前值是否不同，值不同才更新
        if (newEmail != null && !newEmail.equals(currentUser.getEmail())) {
            updateWrapper.set(Users::getEmail, newEmail);
            needUpdate = true;
        }
        if (newPhone != null && !newPhone.equals(currentUser.getPhone())) {
            updateWrapper.set(Users::getPhone, newPhone);
            needUpdate = true;
        }
        if (newAvatar != null && !newAvatar.equals(currentUser.getAvatar())) {
            updateWrapper.set(Users::getAvatar, newAvatar);
            needUpdate = true;
        }

        // 如果有需要更新的字段，执行更新操作
        if (needUpdate) {
            updateWrapper.eq(Users::getUserId, userId); // 更新条件
            usersMapper.update(null, updateWrapper);
        }
        // 更新导师表信息
        updateById(BeanUtil.copyProperties(advisorsDto, Advisors.class).setAdvisorId(id));
    }

    /**
     * 删除导师信息
     *
     * @param id 导师id
     */
    @Transactional
    @Override
    public void delete(Integer id) {
        Advisors advisors = getById(id);
        if (advisors == null) {
            throw new ObjectException(MessageConstants.ADVISOR_NULL);
        }
        removeById(id);
        usersMapper.deleteById(advisors.getUserId());
    }

    /**
     * 获取导师详细信息
     *
     * @param id 导师id
     * @return 导师实体
     */
    @Override
    public AdvisorsVO findById(Integer id) {
        Advisors advisors = getById(id);
        if (advisors == null) {
            throw new ObjectException(MessageConstants.ADVISOR_NULL);
        }
        Users users = usersMapper.selectById(advisors.getUserId());
        AdvisorsVO advisorsVO = BeanUtil.copyProperties(advisors, AdvisorsVO.class);
        advisorsVO.setUser(users);
        return advisorsVO;
    }
}
